package com.lib.common.widget.adapter

import android.content.Context
import com.lib.common.R
import com.lib.common.databinding.ItemLabelListBinding
import com.lib.framework.ext.ddp
import com.lib.framework.widget.adapter.BaseBindingAdapter

/**
 * 标签列表的 adapter，支持多选、单选
 *
 * @author keanbin
 */
abstract class LabelListAdapter<T>(context: Context, dataList: MutableList<T>) :
    BaseBindingAdapter<T, ItemLabelListBinding>(context, dataList) {

    companion object {

        /**
         * 类型
         */
        const val TYPE_SINGLE = 1  // 单选
        const val TYPE_MULTIPLE = 2  // 多选
        const val TYPE_HYBRID = 3  // 混合：单选和多选混合，有的选项和其他选项排斥
    }

    /**
     * 类型
     */
    var mType = TYPE_SINGLE

    /**
     * 监听器
     */
    var mOnLabelListAdapterLisenter: OnLabelListAdapterLisenter<T>? = null

    /**
     * 标签的宽度， 单位是：px
     */
    var mLabelWidth = 120.ddp

    /**
     * 标签的高度， 单位是：px
     */
    var mLabelHeight = 40.ddp

    /**
     * 标签的 TextSize， 单位是：sp
     */
    var mLabseTextSize = 15

    /**
     * 选中的文本颜色
     */
    var mSelectedTextColor = 0xff8281fc.toInt()

    /**
     * 未选中的文本颜色
     */
    var mNoSelectedTextColor = 0xffcacaca.toInt()


    /**
     * 选中的背景
     */
    var mSelectedBackgroundResource = R.drawable.bg_22

    /**
     * 未选中的背景
     */
    var mNoSelectedBackgroundResource = R.drawable.bg_21


    /**
     * 多选 和 混合类型时：选中的map，key 是 position索引， value 是 选中状态
     */
    val mSelectedMap = mutableMapOf<Int, Boolean>()

    /**
     * 单选时：选择的 position索引
     */
    private var mSelectedPosition = -1

    /**
     * 单选时：选择的 Binding
     */
    private var mSelectedBinding: ItemLabelListBinding? = null

    /**
     * 混合类型时：选中的 ItemLabelListBinding 的map，key 是 position索引， value 是 ItemLabelListBinding
     */
    private var mSelectedBindingMap = mutableMapOf<Int, ItemLabelListBinding>()

    /**
     * 混合类型时：只能单选的 item map，key 是 position索引， value 是 数据项
     */
    private var mHybridSingleMap = mutableMapOf<Int, T>()

    override fun getLayoutResId(viewType: Int): Int {
        return R.layout.item_label_list
    }

    override fun onBindItem(binding: ItemLabelListBinding?, item: T, position: Int) {
        setCommonUi(binding)

        when (mType) {
            TYPE_SINGLE -> onBindItemOfSingle(binding, item, position)

            TYPE_MULTIPLE -> onBindItemOfMultiple(binding, item, position)

            TYPE_HYBRID -> onBindItemOfHybrid(binding, item, position)
        }
    }

    /**
     * 单选的 onBindItem
     */
    private fun onBindItemOfSingle(binding: ItemLabelListBinding?, item: T, position: Int) {
        binding?.tvLabel?.text = getTextFromItem(item)

        val isSelected = mSelectedPosition == position
        setSelect(binding, isSelected)

        if (isSelected) {
            mSelectedBinding = binding
        }

        binding?.root?.setOnClickListener {
            if (position == mSelectedPosition) {
                return@setOnClickListener
            }

            setSelect(mSelectedBinding, false)

            mSelectedPosition = position
            mSelectedBinding = binding
            setSelect(mSelectedBinding, true)


            mOnLabelListAdapterLisenter?.onSelecteChange(
                mutableListOf(item),
                mutableListOf(position)
            )
        }
    }

    /**
     * 多选的 onBindItem
     */
    private fun onBindItemOfMultiple(binding: ItemLabelListBinding?, item: T, position: Int) {
        binding?.tvLabel?.text = getTextFromItem(item)

        setSelect(binding, mSelectedMap[position] == true)

        binding?.tvLabel?.setOnClickListener {
            val isSelected = mSelectedMap[position] == true
            if (isSelected) {
                mSelectedMap.remove(position)
            } else {
                mSelectedMap[position] = true
            }

            setSelect(binding, !isSelected)

            val itemList = mutableListOf<T>()
            val positionList = mutableListOf<Int>()
            for ((posit, selected) in mSelectedMap) {
                if (selected) {
                    if (posit >= 0 && posit < data.size) {
                        itemList.add(data[posit])
                    }
                    positionList.add(posit)
                }
            }

            mOnLabelListAdapterLisenter?.onSelecteChange(itemList, positionList)
        }
    }

    /**
     * 混合的 onBindItem
     */
    private fun onBindItemOfHybrid(binding: ItemLabelListBinding?, item: T, position: Int) {
        if (binding == null) return

        binding.tvLabel.text = getTextFromItem(item)
        setSelect(binding, mSelectedMap[position] == true)
        if (mSelectedMap[position] == true) {
            mSelectedBindingMap[position] = binding
        }

        binding.tvLabel.setOnClickListener {
            val isSelected = mSelectedMap[position] == true
            if (mHybridSingleMap[position] != null && isSelected) { // 如果是单选的选项，并且已经选中，就不做任何处理
                return@setOnClickListener
            }

            if (isSelected) { // 设置未选中
                mSelectedMap.remove(position)
                mSelectedBindingMap.remove(position)
            } else { // 设置选中
                if (mHybridSingleMap[position] != null) { // 如果被选中是单选的item，那么需要清空其他所有的选中
                    for ((posit, _) in mSelectedMap) {
                        if (posit != position) {
                            mSelectedMap[posit] = false
                            mSelectedBindingMap[posit]?.let {
                                setSelect(it, false)
                            }
                            mSelectedBindingMap.remove(posit)
                        }
                    }
                } else { // 如果被选中不是单选的item，那么需要清空其他所有单选的选中
                    for ((posit, _) in mSelectedMap) {
                        if (mHybridSingleMap[posit] != null) {
                            mSelectedMap[posit] = false
                            mSelectedBindingMap[posit]?.let {
                                setSelect(it, false)
                            }
                            mSelectedBindingMap.remove(posit)
                        }
                    }
                }

                mSelectedMap[position] = true
                mSelectedBindingMap[position] = binding
            }

            setSelect(binding, !isSelected)

            val itemList = mutableListOf<T>()
            val positionList = mutableListOf<Int>()
            for ((posit, selected) in mSelectedMap) {
                if (selected) {
                    if (posit >= 0 && posit < data.size) {
                        itemList.add(data[posit])
                    }
                    positionList.add(posit)
                }
            }

            mOnLabelListAdapterLisenter?.onSelecteChange(itemList, positionList)
        }
    }

    /**
     * 获取 选中的item 列表
     */
    private fun getSelectedItemList(): List<T> {
        val list = mutableListOf<T>()
        when (mType) {
            TYPE_SINGLE -> {
                if (mSelectedPosition >= 0 && mSelectedPosition < data.size) {
                    list.add(data[mSelectedPosition])
                }
            }

            TYPE_HYBRID,
            TYPE_MULTIPLE -> {
                for ((posit, selected) in mSelectedMap) {
                    if (selected) {
                        if (posit >= 0 && posit < data.size) {
                            list.add(data[posit])
                        }
                    }
                }
            }
        }

        return list
    }

    /**
     * 获取 选中的位置索引 列表
     */
    private fun getSelectedPositList(): List<Int> {
        val list = mutableListOf<Int>()
        when (mType) {
            TYPE_SINGLE -> {
                if (mSelectedPosition >= 0 && mSelectedPosition < data.size) {
                    list.add(mSelectedPosition)
                }
            }

            TYPE_MULTIPLE -> {
                for ((posit, _) in mSelectedMap) {
                    list.add(posit)
                }
            }
        }

        return list
    }

    /**
     * 设置 公共 ui 样式
     */
    private fun setCommonUi(binding: ItemLabelListBinding?) {
        binding?.tvLabel?.textSize = mLabseTextSize.toFloat()

        binding?.tvLabel?.layoutParams?.width = mLabelWidth
        binding?.tvLabel?.layoutParams?.height = mLabelHeight
    }

    /**
     * 设置选中样式
     */
    private fun setSelect(binding: ItemLabelListBinding?, isSelected: Boolean) {
        if (isSelected) {
            binding?.tvLabel?.setTextColor(mSelectedTextColor)
            binding?.tvLabel?.setBackgroundResource(mSelectedBackgroundResource)
        } else {
            binding?.tvLabel?.setTextColor(mNoSelectedTextColor)
            binding?.tvLabel?.setBackgroundResource(mNoSelectedBackgroundResource)
        }
    }

    /**
     * 清空列表需要，清空选中状态
     */
    fun clearSelected() {
        mSelectedPosition = -1
        mSelectedBinding = null

        mSelectedMap.clear()
    }

    /**
     * 设置 混合类型时只能单选的item 索引, 这个需要在添加完数据之后设置，在 setSelected() 之前设置
     *
     * @param singleList 只能单选的item 索引
     */
    fun setHybridSingle(singleList: List<Int>?)  {
        mHybridSingleMap.clear()
        if (singleList.isNullOrEmpty()) return

        for (posit in singleList) {
            if (posit >= 0 && posit < data.size) {
                mHybridSingleMap[posit] = data[posit]
            }
        }
    }
    /**
     * 设置选中, 这个需要在添加完数据之后设置
     *
     * @param selectedPositList 选中的位置列表，如果是单选，只设置列表中第一个选中
     */
    fun setSelected(selectedPositList:List<Int>)  {
        if (selectedPositList.isEmpty()) return

        when (mType) {
            TYPE_SINGLE -> {
                mSelectedPosition = -1
                mSelectedBinding = null
                val selectedPosit = selectedPositList[0]
                if (selectedPosit >= 0 && selectedPosit < data.size) {
                    mSelectedPosition = selectedPosit
                }
            }

            TYPE_MULTIPLE -> {
                mSelectedMap.clear()
                for (selectedPosit in selectedPositList) {
                    if (selectedPosit >= 0 && selectedPosit < data.size) {
                        mSelectedMap[selectedPosit] = true
                    }
                }
            }

            TYPE_HYBRID -> {
                mSelectedMap.clear()
                for (selectedPosit in selectedPositList) {
                    if (selectedPosit >= 0 && selectedPosit < data.size) {
                        if (mHybridSingleMap[selectedPosit] != null) {
                            mSelectedMap.clear()
                            mSelectedMap[selectedPosit] = true
                            break
                        }

                        mSelectedMap[selectedPosit] = true
                    }
                }
            }
        }
    }

    /**
     * 从数据项中获取文本
     */
    abstract fun getTextFromItem(item: T): String


    /**
     * 监听器
     */
    interface OnLabelListAdapterLisenter<T> {

        /**
         * 选中改变回调
         *
         * @param itemList 选中的列表，单选时只有一个
         * @param positionList 选中索引的列表，单选时只有一个
         */
        fun onSelecteChange(itemList: List<T>, positionList: List<Int>)
    }
}